package com.df.my_net_game.common.controller;

import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Map;
import java.util.Set;

@Slf4j
@AllArgsConstructor
public class ProtobufClassScanner {
    /**
     * 资源加载器
     */
    private final ResourceLoader resourceLoader;
    /**
     * 环境
     */
    private final Environment environment;

    @PostConstruct
    public void init() {
        if (log.isInfoEnabled()){
            log.info("start DataPermissionRegister ");
        }

        ClassPathScanningCandidateComponentProvider scanner = getScanner();
        scanner.setResourceLoader(resourceLoader);

        // 设置扫描器scanner扫描的过滤条件 还支持扫描指定类型（包括继承他的类）  AssignableTypeFilter
        AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(ProtobufClass.class);
        scanner.addIncludeFilter(annotationTypeFilter);

        // 获取指定要扫描的basePackages
        Set<String> basePackages = Set.of("com.df.my_net_game.proto");

        // 遍历每一个basePackages
        for (String basePackage : basePackages) {
            // 通过scanner获取basePackage下的候选类(有标@SimpleRpcClient注解的类)
            Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
            // 遍历每一个候选类，如果符合条件就把他们注册到容器
            for (BeanDefinition candidateComponent : candidateComponents) {
                if (candidateComponent instanceof AnnotatedBeanDefinition beanDefinition) {
                    // candidateComponent 有很多class的信息，下面举例是获取class上的指定注解
                    AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
                    Map<String, Object> dataPermissionAttrs = annotationMetadata.getAnnotationAttributes(ProtobufClass.class.getCanonicalName());
                    // ...剩余处理，注册 或者其他
                }
            }
        }

        if (log.isInfoEnabled()){
            log.info("ProtobufClass scan success!");
        }
    }



    /**
     * 创建扫描器
     */
    protected ClassPathScanningCandidateComponentProvider getScanner() {
        return new ClassPathScanningCandidateComponentProvider(false, environment) {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                boolean isCandidate = false;
                if (beanDefinition.getMetadata().isIndependent()) {
                    // 注解类型的class就不要了
                    if (!beanDefinition.getMetadata().isAnnotation()) {
                        isCandidate = true;
                    }
                }
                return isCandidate;
            }
        };
    }
}

